package com.gnerv.battle.boot.module.base.interceptor;

import com.gnerv.battle.boot.common.base.annotation.log.LogController;
import com.gnerv.battle.boot.common.tools.UUIDTools;
import com.gnerv.battle.boot.common.spring.tool.IpTools;
import com.gnerv.battle.boot.module.base.model.entity.AuditApi;
import com.gnerv.battle.boot.module.base.service.AuditApiService;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.security.Principal;

/**
 * @author Gnerv LiGen
 */
@Slf4j
public class AuditApiMethodInterceptor implements MethodInterceptor {

    private final AuditApiService auditApiService;

    public AuditApiMethodInterceptor(AuditApiService auditApiService) {
        this.auditApiService = auditApiService;
    }

    @Nullable
    @Override
    public Object invoke(@Nonnull MethodInvocation invocation) throws Throwable {
        String ukId = UUIDTools.lower();
        AuditApi auditApi = new AuditApi();
        auditApi.setUkId(ukId);
        auditApi.setStatus("fail");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(attributes != null){
            Principal userPrincipal = attributes.getRequest().getUserPrincipal();
            if(userPrincipal != null){
                auditApi.setAccount(userPrincipal.getName());
            }
            auditApi.setIp(IpTools.getIpAddress(attributes.getRequest()));
            auditApi.setUrl(attributes.getRequest().getRequestURI());
            auditApi.setType(attributes.getRequest().getMethod());
        }
        LogController logController = invocation.getMethod().getAnnotation(LogController.class);
        if(logController != null){
            auditApi.setReason(logController.value());
        }
        try {
            auditApiService.create(auditApi);
        } catch (Exception exception) {
            log.info(exception.getMessage());
        }
        Object result;
        try {
            result = invocation.proceed();
        } catch (Exception e) {
            try {
                auditApi = new AuditApi();
                auditApi.setUkId(ukId);
                auditApi.setReason(e.getMessage());
                auditApi.setException(e.toString());
                auditApiService.updateByUkId(auditApi);
            } catch (Exception exception) {
                log.info(exception.getMessage());
            }
            throw e;
        }
        try {
            auditApiService.updateStatusByUkId(ukId, "success");
        } catch (Exception exception) {
            log.info(exception.getMessage());
        }
        return result;
    }

}
